/**
 * 
 */
package ui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.lang.management.ManagementFactory;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutionException;
import java.util.logging.Logger;

import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.DropMode;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.ListSelectionModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;

import servent.Servent;
import workers.Busquedas;
import workers.TimedWorker;

import application.DownloadState;
import application.FileStateAgent;
import application.MachineID;
import application.MachineIDProvider;
import application.Server;
import application.SizeSearchPredicate;
import application.UniqueFileID;

/**
 * @author Nixon Duarte
 *
 */
@SuppressWarnings("serial")
public class ClientUI extends JFrame implements ActionListener 
{
	JFrame frameCliente;
	JTabbedPane tabPrincipal; 
	JPanel panelSubirBajarBuscar;
	
	
	//para subir un archivo
	JPanel pannelSubir;
	JButton btnSubir;
	JSpinner spnSubir;
	JLabel lblSubirArchivo;
	JLabel lblSubirVeces;
	JButton btnEscogerArchivo;
	//JTree tree = null;
	///

	
	///
	JPanel subirBajarBuscarSur;
	///
	
	////para bajar un archivo
	JPanel panelDescargar;
	JButton btnRecibir;
	JSpinner spnBajar;
	JLabel labelBajar;
	JLabel labelVeces;
	/////
		
	///panel para abrir
	JPanel panelAbrir;
	JPanel panelAbrirNorte;
	JPanel panelAbrirSur;
	JButton btnAbrirArchivo;
	JTextField txtArchivo;
	JTextField txtAbrirArchivo;
	JList listaArchivosCliente;
	JScrollPane panelListaCliente;
	JLabel lblAbrirArchivo;
	JButton btnBuscarArchivoAbrir;
	JButton btnRefrecsarListaArchivos;
	///
	
	///para buscar archivos
	JPanel panelBuscar;
	JTextField txtBuscar;
	JButton btnBuscar;
	JLabel labelBuscar;
	JComboBox comboBoxTipoBusqueda;
	SearchResultsListModel searchListModel;
	///
	
	///comun
	JScrollPane panelLista;
	JList listaArchivos;
	///
	
	//panel de tiempos
	JPanel panelTiempos;
	JPanel panelBotonesTiempos;
//	JButton btnDumpLog;
	JButton btnClearDone;
	JButton btnCancelTask;
	JScrollPane panelListaTiempos;
	JList listaTiempos;
	TimeWorkerListModel twlm;
	//
	
	//Panel de Peers
	JPanel panelPeers;
	JList listaPeers;
	//
	
	/*Panel Organizacion logica archivos*/
	JScrollPane panelArbol;
	JList listaArbol;	
	/*fin organizacion logica archivos*/
	
	/* panel estados guardados */
	JPanel panelEstados;
	JList listaEstados;
	JButton btnRetomarEstado;
	/////
	
	Servent servent;

	protected JFileChooser fileChooser = new JFileChooser();
	private long initTime;

	public ClientUI( Servent servent )
	{
		initTime = System.currentTimeMillis();
		this.servent = servent;

		frameCliente = new JFrame(ManagementFactory.getRuntimeMXBean().getName() + " | " + servent.getClient().getRootDir().getPath() );
		frameCliente.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//frameCliente.setLayout( new FlowLayout() );
		tabPrincipal = new JTabbedPane();
		frameCliente.add( tabPrincipal );

		panelSubirBajarBuscar = new JPanel();
		panelSubirBajarBuscar.setLayout(new BorderLayout());
		
		JPanel panelNorteBuscarBajarSubir = new JPanel();
		panelNorteBuscarBajarSubir.setLayout( new BorderLayout() );				

		///para buscar archivos
		panelBuscar = new JPanel();
		panelBuscar.setLayout(new FlowLayout());
		panelBuscar.setBorder( BorderFactory.createLineBorder(Color.black));
		labelBuscar = new JLabel( "Buscar archivos por ");

		Object items[] = {Busquedas.BUSCAR_POR_ANO,
				Busquedas.BUSCAR_POR_FORMATO_ARCHIVO,
				Busquedas.BUSCAR_POR_NOMBRE_ALBUM,
				Busquedas.BUSCAR_POR_NOMBRE_ARCHIVO,
				Busquedas.BUSCAR_POR_NOMBRE_ARTISTA,
				Busquedas.BUSCAR_POR_NOMBRE_CANCION,
				Busquedas.BUSCAR_POR_TAMANO};
		comboBoxTipoBusqueda = new JComboBox(items);
		comboBoxTipoBusqueda.setSelectedItem(Busquedas.BUSCAR_POR_NOMBRE_ARCHIVO);
		txtBuscar = new JTextField( 10 );
		btnBuscar = new JButton("Buscar");
		btnBuscar.setActionCommand( "Buscar");
		btnBuscar.addActionListener(this);
		panelBuscar.add( labelBuscar );
		panelBuscar.add( comboBoxTipoBusqueda );
		panelBuscar.add( txtBuscar );
		panelBuscar.add( btnBuscar );
		
		panelNorteBuscarBajarSubir.add( panelBuscar , BorderLayout.SOUTH);
		//
		
		panelSubirBajarBuscar.add( panelNorteBuscarBajarSubir, BorderLayout.NORTH);		
		
		
		///comun
		searchListModel = new SearchResultsListModel();
		listaArchivos =  new JList( searchListModel);
		listaArchivos.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
		panelLista = new JScrollPane( listaArchivos );
		panelSubirBajarBuscar.add(panelLista, BorderLayout.CENTER);				
		
		//frameCliente.add( panelLista , BorderLayout.CENTER );
		//////

		
		////para bajar un archivo
		subirBajarBuscarSur = new JPanel();
		subirBajarBuscarSur.setLayout(new BorderLayout());

		
		panelDescargar = new JPanel();
		panelDescargar.setLayout(new FlowLayout());
		panelDescargar.setBorder( BorderFactory.createLineBorder(Color.black) );
		btnRecibir = new JButton( "Descargar" );
		btnRecibir.setActionCommand("Bajar");
		btnRecibir.addActionListener(this);
		spnBajar = new JSpinner();
		spnBajar.setValue(1);
		labelBajar = new JLabel ("Descargar archivo seleccionado ");
		labelVeces = new JLabel( "veces" );
		Dimension d = spnBajar.getPreferredSize();
		spnBajar.setPreferredSize(new Dimension(d.width +20 , d.height ) );
		
		panelDescargar.add( labelBajar );
		panelDescargar.add( spnBajar );
		panelDescargar.add( labelVeces );
		panelDescargar.add( btnRecibir );
		
		subirBajarBuscarSur.add(panelDescargar, BorderLayout.NORTH );
		
		panelSubirBajarBuscar.add(subirBajarBuscarSur, BorderLayout.SOUTH);
		/////
		        
		tabPrincipal.addTab( "Buscar", panelSubirBajarBuscar );		

		
		
		//// abrir archivos
		panelAbrir = new JPanel();
		panelAbrir.setLayout( new BorderLayout());
		panelAbrirNorte = new JPanel();
		panelAbrirNorte.setLayout( new FlowLayout());
		panelAbrirSur = new JPanel();
		panelAbrirSur.setLayout( new FlowLayout());
		
		btnBuscarArchivoAbrir = new JButton("...");
		btnBuscarArchivoAbrir.setActionCommand("***");
		btnBuscarArchivoAbrir.addActionListener(this);
		btnRefrecsarListaArchivos = new JButton("Refrescar Lista");
		btnRefrecsarListaArchivos.setActionCommand("Refrescar");
		btnRefrecsarListaArchivos.addActionListener(this);		
		btnAbrirArchivo = new JButton("Abrir");
		btnAbrirArchivo.setActionCommand("Abrir");
		btnAbrirArchivo.addActionListener(this);
		
		txtAbrirArchivo = new JTextField( 30 );
		lblAbrirArchivo = new JLabel("Abrir archivo");
		
		listaArchivosCliente =  new JList( );
		listaArchivosCliente.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
		panelListaCliente = new JScrollPane( listaArchivosCliente );	
		
		
		panelAbrirNorte.add(lblAbrirArchivo);
		panelAbrirNorte.add(txtAbrirArchivo);
		panelAbrirNorte.add(btnBuscarArchivoAbrir);
		panelAbrirSur.add(btnRefrecsarListaArchivos);
		panelAbrirSur.add(btnAbrirArchivo);
		panelAbrir.add(panelAbrirNorte, BorderLayout.NORTH);
		panelAbrir.add(panelListaCliente, BorderLayout.CENTER);		
		panelAbrir.add(panelAbrirSur, BorderLayout.SOUTH);
		panelAbrir.add(panelListaCliente, BorderLayout.CENTER);
		
		tabPrincipal.addTab( "Abrir", null, panelAbrir, "Abrir Archivos" );		
		////////
		
		//panel de tiempos
		panelTiempos = new JPanel();
		panelBotonesTiempos = new JPanel();
		panelBotonesTiempos.setLayout( new FlowLayout() );
//		btnDumpLog = new JButton( "escribir csv");
//		btnDumpLog.setActionCommand("log");
//		btnDumpLog.addActionListener(this );
	
		btnClearDone = new JButton ("Purgar");
		btnClearDone.addActionListener(this );
		btnClearDone.setActionCommand("purge");
 
		btnCancelTask = new JButton("Cancelar");
		btnCancelTask.addActionListener(this);
		btnCancelTask.setActionCommand("cancel");
		
//		panelBotonesTiempos.add( btnDumpLog );
		panelBotonesTiempos.add( btnClearDone );
		panelBotonesTiempos.add( btnCancelTask );
		
		twlm = servent.getTimeWorkerListModel();
		listaTiempos = new JList( twlm );
		panelListaTiempos = new JScrollPane ( listaTiempos );
		//

		panelTiempos.setLayout( new BorderLayout() );
		panelTiempos.add( panelBotonesTiempos , BorderLayout.NORTH );
		panelTiempos.add(panelListaTiempos, BorderLayout.CENTER);
		
		tabPrincipal.addTab("Tareas", panelTiempos );
		
		
		
		///Estados
		panelEstados = new JPanel(new BorderLayout());
		listaEstados = new JList( FileStateAgent.getInstance() );
		JPanel panelNorteEstados = new JPanel();
		btnRetomarEstado  = new JButton("Continuar Tarea");
		btnRetomarEstado.setActionCommand("resume");
		btnRetomarEstado.addActionListener(this);
		panelNorteEstados.add(btnRetomarEstado);
		
		panelEstados.add(panelNorteEstados, BorderLayout.NORTH);
		panelEstados.add(new JScrollPane(listaEstados));

		
		tabPrincipal.addTab("Estados", panelEstados);
		//

		
		
		
		
		////tab con peers... y para enviar archivo
		//para subir un archivo
 
		pannelSubir = new JPanel();
		pannelSubir.setLayout( new FlowLayout() );
		btnSubir = new JButton("Subir");
		btnSubir.setActionCommand("Subir");
		btnSubir.addActionListener(this);
		btnEscogerArchivo = new JButton("...");
		btnEscogerArchivo.setActionCommand("...");
		btnEscogerArchivo.addActionListener(this);
		spnSubir = new JSpinner();
		spnSubir.setValue(1);		
		d = spnSubir.getPreferredSize();
		spnSubir.setPreferredSize( new Dimension( d.width + 20, d.height ) );
		lblSubirArchivo = new JLabel("Subir archivo");
		lblSubirVeces = new JLabel("veces");
		txtArchivo = new JTextField( 30 );							
		
		pannelSubir.add(lblSubirArchivo);
		pannelSubir.add(txtArchivo);
		pannelSubir.add(btnEscogerArchivo);
		pannelSubir.add(spnSubir);
		pannelSubir.add(lblSubirVeces);
		pannelSubir.add(btnSubir);
		pannelSubir.setBorder(BorderFactory.createLineBorder(Color.black));
		
		
		//los pares
		listaPeers = new JList();
		listaPeers.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		listaPeers.setModel(MachineIDProvider.getInstance());
		
		panelPeers = new JPanel( new BorderLayout() );
		panelPeers.add( new JLabel("Amigos en la red"), BorderLayout.NORTH);
		panelPeers.add(pannelSubir, BorderLayout.SOUTH );				
		panelPeers.add( new JScrollPane(listaPeers), BorderLayout.CENTER);
		
		tabPrincipal.addTab("Enviar", panelPeers );
		///////////
		
		
		
		/*Arbol*/
		this.SimpleTree();
		/*fin arbol*/
		
		
		frameCliente.pack();
		frameCliente.setVisible(true);
		
	}
	
	public void actionPerformed(ActionEvent e)
	{
		System.out.println(e.getActionCommand());
		if (e.getActionCommand().equals("..."))
		{
			JFileChooser fc = new JFileChooser( servent.getClient().getRootDir() );
			fc.setMultiSelectionEnabled(false);
			fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
			if( fc.showOpenDialog( frameCliente ) == JFileChooser.APPROVE_OPTION ){
				txtArchivo.setText( fc.getSelectedFile().getPath());
			}
		}
		if (e.getActionCommand().equals("***"))
		{
			JFileChooser fc = new JFileChooser( servent.getClient().getRootDir() );
			fc.setMultiSelectionEnabled(false);
			fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
			if( fc.showOpenDialog( frameCliente ) == JFileChooser.APPROVE_OPTION ){
				txtAbrirArchivo.setText( fc.getSelectedFile().getPath());
			}
		}		
		if (e.getActionCommand().equals("Bajar"))
		{
			if( listaArchivos.getSelectedValue() != null ){
				Integer max = (Integer) spnBajar.getValue();
				for( int i = 0; i < max.intValue() ; i ++ ){
					Object o = listaArchivos.getSelectedValue();
					if( o instanceof UniqueFileID ){
						UniqueFileID fileID = (UniqueFileID) o;
						servent.getClient().Bajar( fileID );
					}
					else{
						Logger.getLogger(Server.loggerName).severe("Esperabamos un UniqueFileID en la lista del GUI pero hay " + o.getClass().getName());
					}
				}
			}
			else {
				JOptionPane.showMessageDialog( frameCliente , "Seleccionar un archivo de la lista" );
			}
		}
		else if (e.getActionCommand().equals("Subir")){
			File f = new File( txtArchivo.getText() );
			if( f.exists() ){
				Integer max = (Integer) spnSubir.getValue();
				for( int i = 0; i< max.intValue(); i++ ){
					servent.getClient().Subir( f , (MachineID) listaPeers.getSelectedValue() );
				}
			}
		}
		else if (e.getActionCommand().equals("simul")) {
			File f = new File( txtArchivo.getText() );
			if( listaArchivos.getSelectedValue() != null && f.exists() ){
				Integer numSubidas = (Integer) spnSubir.getValue();
				Integer numBajadas = (Integer) spnBajar.getValue();
				
				Object o = listaArchivos.getSelectedValue();
				if( o instanceof UniqueFileID ){
					UniqueFileID fileID = (UniqueFileID) o;
					while( numSubidas > 0 || numBajadas > 0 ){
						if( numSubidas > 0 ) servent.getClient().Subir( f ,  (MachineID) listaPeers.getSelectedValue() );
						if( numBajadas > 0 ) servent.getClient().Bajar( fileID );
						numSubidas --;
						numBajadas --;
					}
				}
				else{
					Logger.getLogger(Server.loggerName).severe("Esperabamos un UniqueFileID en la lista del GUI pero hay " + o.getClass().getName());
				}
			}
			else {
				JOptionPane.showMessageDialog( frameCliente , "Seleccionar un archivo de la lista y \n elegir un archivo para subir" );
			}
		}
		else if (e.getActionCommand().equals("Abrir"))
		{
			System.out.println("Open File: " + txtAbrirArchivo.getText());
			try {
				String archivoSel = "";
				if (txtAbrirArchivo.getText() != null 
						&& txtAbrirArchivo.getText().length() > 0)
				{
					archivoSel = txtAbrirArchivo.getText();
				}
				else if( listaArchivosCliente.getSelectedValue() != null 
						&& listaArchivosCliente.getSelectedValue().toString().length() > 0)
				{
					servent.getClient().getRootDir();
					archivoSel = servent.getClient().getRootDir().getAbsolutePath() + File.separatorChar + listaArchivosCliente.getSelectedValue().toString();
				}
					
				if (archivoSel.endsWith(".mp3"))
				{
					  ProcessBuilder p=new ProcessBuilder("cmd.exe","/c","start", "\"DummyTitle\"", archivoSel );					  
					  p.start();					
				}
				else if (archivoSel.endsWith(".pdf"))
				{
					  File file = new File(archivoSel);
			          Desktop.getDesktop().open(file);					
				}				
				else
				{
					JOptionPane.showMessageDialog(null, "Solo archivos tipo .mp3 o .pdf", "**ALERTA**", 1);
				}
			} catch (Exception e1) {
			         e1.printStackTrace();
			}			
		}		
		else if (e.getActionCommand().equals("Refrescar"))
		{
			File listFile[] = servent.getClient().getRootDir().listFiles();
			DefaultListModel dm = new DefaultListModel();
			for (int i = 0; i < listFile.length; i++) {
				String name = listFile[i].getName();
				if(name.matches(".*(doc|pdf|docx|mp3|wav|wma|mpg|avi|mpeg)")){
					if(listFile[i].lastModified() > initTime ){
						Date d = new Date(listFile[i].lastModified());
						DateFormat df = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z");
						dm.addElement( listFile[i].getName() + " [Downloaded " + df.format(d) + "]");
					}
					else{
						dm.addElement(listFile[i].getName());					
					}
				}
			}
			listaArchivosCliente.removeAll();
			listaArchivosCliente.setModel(dm);
		}
		else if (e.getActionCommand().equals("Buscar"))
		{
			
			try {
				searchListModel.clear();
				long lowerBound = 0;
				long upperBound = 100000000;
				servent.getClient().Buscar( comboBoxTipoBusqueda.getSelectedItem().toString(), txtBuscar.getText() , searchListModel);
				searchListModel.setPredicate( new SizeSearchPredicate(lowerBound, upperBound));
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			} catch (ExecutionException e1) {
				e1.printStackTrace();
			}			
		}
		else if (e.getActionCommand().equals("purge")) {
			twlm.clearFinishedTasks();
//		}else if (e.getActionCommand().equals("log")) {
//            JFileChooser jfc = new JFileChooser( servent.getClient().getRootDir() );
//            jfc.setDialogType(JFileChooser.SAVE_DIALOG);
//            jfc.setApproveButtonText("Guardar");
//            if( jfc.showSaveDialog( frameCliente ) == JFileChooser.APPROVE_OPTION ){
//				File f = jfc.getSelectedFile();
//				twlm.requestFileDump( f , servent.getClient().getDescription() );
//            }
		}else if( e.getActionCommand().equals("cancel")){
			Object selectedTasks[] = listaTiempos.getSelectedValues();
			for (int i = 0; i < selectedTasks.length; i++) {
				((TimedWorker) selectedTasks[i]).cancelTask();
			}
		}else if ( e.getActionCommand().equals("resume")){
			Object selectedState = listaEstados.getSelectedValue();
			if( selectedState != null ){
				servent.getClient().reanudarDescarga((DownloadState) selectedState);
			}
		}
	}

	  public void SimpleTree() {
		  SimpleTree(0);
	  }
	  public void SimpleTree(int option) {
		  		    
		    File listFile = new File(servent.getClient().getRootDir().getAbsolutePath());
		    
		    String[] treelabels =   { 
				     "Todos", 
				     "Video", 
				     "Audio",
				     "Documentos",
				     "Otros"};

		    String[] files = listFile.list();
		    
		    DefaultMutableTreeNode[] nodes = new DefaultMutableTreeNode[treelabels.length];
		    DefaultMutableTreeNode[] videoNodes = new DefaultMutableTreeNode[files.length];
		    DefaultMutableTreeNode[] audioNodes = new DefaultMutableTreeNode[files.length];
		    DefaultMutableTreeNode[] docsNodes = new DefaultMutableTreeNode[files.length];
		    DefaultMutableTreeNode[] otrosNodes = new DefaultMutableTreeNode[files.length];

		    for (int i=0; i < treelabels.length; i++) {
		      nodes[i] = new DefaultMutableTreeNode(treelabels[i]); 
		    }
		    
		    for (int i=1; i < nodes.length; i++) {
		        nodes[0].add(nodes[i]); 
		    }
		    
		    for (int i=0; i < files.length; i++) {    	
		    	if (files[i].matches(".*(mpg|avi|mpeg)"))
		    	{
		    		videoNodes[i] = new DefaultMutableTreeNode(files[i]); 
		    		nodes[1].add(videoNodes[i]);
		    	}
		    }
		    for (int i=0; i < files.length; i++) {
		    	
		    	if (files[i].matches(".*(mp3|wav|wma)"))
		    	{    	
		    		audioNodes[i] = new	DefaultMutableTreeNode(files[i]); 
		    		nodes[2].add(audioNodes[i]);
		    	}
		    }

		    for (int i=0; i < files.length; i++) {    	
		    	if (files[i].matches(".*(doc|pdf|docx)"))
		    	{
		    		docsNodes[i] = new DefaultMutableTreeNode(files[i]); 
		    		nodes[3].add(docsNodes[i]);
		    	}
		    }

		    for (int i=0; i < files.length; i++) {
		    	if (!files[i].matches(".*(doc|pdf|docx|mp3|wav|wma|mpg|avi|mpeg)"))
		    	{    	
		    		otrosNodes[i] = new	DefaultMutableTreeNode(files[i]); 
		    		nodes[4].add(otrosNodes[i]);
		    	}
		    }
		    

		    DefaultTreeModel model = new DefaultTreeModel(nodes[0]);
		    final JTree tree = new JTree(model);
		    
		    MouseListener ml = new MouseAdapter() 
		    {
		         public void mousePressed(MouseEvent e) 
		         {
		             // Se obtiene el path para esa fila. Con el path podemos obtener
		             // los nodos.
		             TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
		             if (selPath != null)
		             {
		            	 SimpleTree(1);
		             }
		        }
		    };
		    tree.addMouseListener(ml);
		    
		    tree.setDropMode(DropMode.ON);
		    panelArbol = new JScrollPane(tree);
		    //JScrollPane scroll = new JScrollPane(tree);		    
		    getContentPane().add(panelArbol, BorderLayout.CENTER);
		    if (option == 1)
		    {
		    	tabPrincipal.removeTabAt(4);
		    	tabPrincipal.addTab("Carpetas", panelArbol );
		    	tabPrincipal.setSelectedIndex(4);		    	
		    }
		    else
		    	tabPrincipal.addTab("Carpetas", panelArbol );
		    
//################
		    /*
			listaArbol = new JList();
			listaArbol.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
			listaArbol.setModel(servent.getMachineIDProvider());
			panelArbol = new JScrollPane(listaArbol);
			
			tabPrincipal.addTab("Carpetas", panelArbol );		
		    */
		  }                                                               
	
}		
